/* Copyright (c) 2024 Qualcomm Technologies International, Ltd. */
/* %%version */

#include <service_handle.h>

#include "gatt_ots_client.h"
#include "gatt_ots_client_init.h"
#include "gatt_ots_client_debug.h"
#include "gatt_ots_client_common_util.h"

extern GattOtsClient *otsClientMain;

static bool gattOtscRegisterWithGatt(GattClientRegistrationParams *regParam,
                                     GOTSC                        *gattOtsClient)
{
    CsrBtTypedAddr addr;
    bool registered = FALSE;

    gattOtsClient->srvcElem->gattId = CsrBtGattRegister(GATT_OTS_CLIENT_IFACEQUEUE);

    if (gattOtsClient->srvcElem->gattId)
    {
        if (CsrBtGattClientUtilFindAddrByConnId(regParam->cid, &addr))
        {
            CsrBtGattClientRegisterServiceReqSend(gattOtsClient->srvcElem->gattId,
                                                  regParam->startHandle,
                                                  regParam->endHandle,
                                                  addr);
            registered = TRUE;
        }
    }

    return (registered);
}

void GattOtscSendInitCfm(GOTSC          *gattOtsClient,
                         CsrBtResultCode resultCode,
                         CsrBtSupplier   supplier)
{
    GattOtscInitCfm *message = CsrPmemZalloc(sizeof(*message));

    message->svcHandle  = gattOtsClient->srvcElem->service_handle;
    message->cid        = gattOtsClient->srvcElem->cid;
    message->resultCode = resultCode;
    message->supplier   = supplier;

    GATT_OTS_CLIENT_INFO("GOTSC : GattOtscSendInitCfm: svcHandle(0x%02x)\n", gattOtsClient->srvcElem->service_handle);

    CsrMemCpy(&message->suppFeatures,
              &gattOtsClient->deviceData.supportedFeatures,
              sizeof(GattOtscSupportedFeatures));

    GattOtscMessageSend(gattOtsClient->appTask, GATT_OTSC_INIT_CFM, message);
}

void GattOtscInitReq(AppTask                   theAppTask,
                     const GattOtscInitData   *initData,
                     const GattOtscDeviceData *deviceData)
{
    GOTSC *gattOtsClient = NULL;
    GattClientRegistrationParams registration_params;
    ServiceHandle svcHandle = 0;

    if ((theAppTask == CSR_SCHED_QID_INVALID) || (initData == NULL))
    {
        GATT_OTS_CLIENT_PANIC("GOTSC : Invalid initialization parameters\n");
    }
    svcHandle = GattOtscGetServiceHandle(&gattOtsClient, &(otsClientMain->serviceHandleList));

    GATT_OTS_CLIENT_INFO("GOTSC : GattOtscInitReq: svcHandle(0x%02x)\n", svcHandle);

    if (gattOtsClient)
    {
        memset(&registration_params, 0, sizeof(GattClientRegistrationParams));

        gattOtsClient->libTask = GATT_OTS_CLIENT_IFACEQUEUE;

        /* Store the Task function parameter. All library messages need to be sent here */
        gattOtsClient->appTask = theAppTask;

        if (deviceData)
        {
            CsrMemCpy(&(gattOtsClient->deviceData), deviceData, sizeof(GattOtscDeviceData));
        }
        else
        {
            CsrMemSet(&(gattOtsClient->deviceData), 0, sizeof(GattOtscDeviceData));
        }

        /* Save the start and the end handles */
        gattOtsClient->deviceData.startHandle = initData->startHandle;
        gattOtsClient->deviceData.endHandle   = initData->endHandle;

        /* Initialize other fields */
        gattOtsClient->writeCccCount = 0;
        gattOtsClient->pendingHandle = 0;
        gattOtsClient->pendingCmd    = OTSC_PENDING_OP_NONE;
        gattOtsClient->srvcElem->cid = initData->cid;
        gattOtsClient->btConnId      = CSR_BT_CONN_ID_INVALID;

        /* Setup data required for Gatt Client to be registered with the GATT */
        registration_params.cid         = initData->cid;
        registration_params.startHandle = initData->startHandle;
        registration_params.endHandle   = initData->endHandle;

        if (gattOtscRegisterWithGatt(&registration_params, gattOtsClient))
        {
            if (!deviceData)
            {
                CsrBtGattDiscoverAllCharacOfAServiceReqSend(gattOtsClient->srvcElem->gattId,
                                                            gattOtsClient->srvcElem->cid,
                                                            gattOtsClient->deviceData.startHandle,
                                                            gattOtsClient->deviceData.endHandle);
            }
            else
            {
                GattOtscSendInitCfm(gattOtsClient,
                                    GATT_OTSC_RESULT_CODE_SUCCESS,
                                    GATT_SUPPLIER_OTS_CLIENT);
            }
        }
        else
        {
            GattOtscSendInitCfm(gattOtsClient,
                                GATT_OTSC_RESULT_CODE_OPERATION_FAILED,
                                GATT_SUPPLIER_OTS_CLIENT);
            GATT_OTS_CLIENT_ERROR("GOTSC: GATT Registeration failed !\n");
        }
    }
    else
    {
        GattOtscInitCfm *message = CsrPmemZalloc(sizeof(*message));

        message->cid        = initData->cid;
        message->svcHandle  = INVALID_PROFILE_HANDLE;
        message->resultCode = GATT_OTSC_RESULT_CODE_OPERATION_FAILED;
        message->supplier   = GATT_SUPPLIER_OTS_CLIENT;

        GattOtscMessageSend(theAppTask, GATT_OTSC_INIT_CFM, message);

        GATT_OTS_CLIENT_ERROR("GOTSC: OTS client instance not found !\n");
    }

    CSR_UNUSED(svcHandle);
}

void GattOtscInit(void **gash)
{
    otsClientMain = CsrPmemZalloc(sizeof(*otsClientMain));
    *gash         = otsClientMain;

    if (otsClientMain)
    {
        CsrCmnListInit(&otsClientMain->serviceHandleList,
                       0,
                       GattOtscInitServiceHandleList,
                       NULL);
    }
}

GattOtsClient *GattOtscGetMainInstance(void)
{
    return otsClientMain;
}

#ifdef ENABLE_SHUTDOWN
void GattOtscDeInit(void **gash)
{
    CsrCmnListDeinit(&otsClientMain->serviceHandleList);
    CsrPmemFree(otsClientMain);
}
#endif

